package com.xtsoft.platform.base.system.controller;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;

import com.xtsoft.core.controller.GenericController;

import com.xtsoft.core.repository.QueryFilter;
import com.xtsoft.core.repository.QueryResult;
import com.xtsoft.core.repository.Sort;
import com.xtsoft.core.utils.ResultMessage;
import com.xtsoft.core.utils.ResultMsg;
import com.xtsoft.core.utils.StringUtils;
import com.xtsoft.core.utils.UUIDGenerator;

import com.xtsoft.platform.base.system.config.JwtTokenProvider;
import com.xtsoft.platform.base.system.domain.SysUser;
import com.xtsoft.platform.base.system.service.SysOrganizeService;
import com.xtsoft.platform.base.system.service.SysUserService;
import com.xtsoft.platform.globe.Constants.Constants;
import com.xtsoft.platform.globe.utils.EncryptUtil;
import com.xtsoft.platform.globe.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;


import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static org.springframework.http.ResponseEntity.ok;


/**
 * 
 * @ClassName: SysUser
 *             <p>
 *             用户处理类
 *             </p>
 * @author: Codegen-代码生成器
 * @date: 2019年12月3日 上午10:59:46
 */
@Tag(name =  "用户--处理接口")
@RestController
public class SysUserController extends GenericController {

	private final Logger log = LoggerFactory.getLogger(SysUserController.class);
	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private JwtTokenProvider jwtTokenProvider;

	private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	@Autowired
	private SysUserService sysUserService;
	
	//增加组织
	/**
	 * shijunwei+
	 */
	@Autowired
	private SysOrganizeService sysOrganizeService;

	/**
	 * <p>
	 * 新增一个用户
	 * </p>
	 * 
	 * @param sysUser 要新增的用户
	 * @return ResponseEntity<ResultMsg>, ResultMsg的Data中包含 用户
	 * @throws URISyntaxException 如果URI语法不正确，则抛URI语法异常
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	@Parameter(name = "sysUser", description = "要新增的用户", required = false)
	@Operation(summary  = "新增，根据前台传递的用户新增")
	@PostMapping("/sysUser/add")
	public ResponseEntity<ResultMsg> add(
			@RequestBody SysUser sysUser)
			throws URISyntaxException {
		if (null == sysUser) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "新增用户失败，传递的用户为空"), HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("新增用户开始......", user.getLoginId(), user.getUsername(),
				getClientIp());
		if (!StringUtils.isEmpty(sysUser.getUserId())) {
			log.info("新增用户失败，新用户不能具有UserId属性值", user.getLoginId(), user.getUsername(),
					getClientIp());
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "新增用户失败，新用户不能具有UserId属性值"), HttpStatus.OK);
		}
		//设置关联的企业，默认为当前登录用户企业
		sysUser.setSysOrganize(sysOrganizeService.getByNodeId(sysUser.getSysOrganize().getNodeId()));
		/**
		 * //String encodingId =同时修改重置默认的密码：
		 */
		//sysUser.setPassword(EncryptUtil.encrypt("123456", "bcrypt"));
		sysUser.setPassword(EncryptUtil.encrypt(Constants.InitPassword, "bcrypt"));
		
		//sysUser.setFilePath(Constants.DEFAULT_USER_IMAGE);// 默认用户图标,不存在
		SysUser result = sysUserService.save(sysUser);
		log.info("新增用户成功", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "新增成功", result), HttpStatus.OK);
	}

	/**
	 * <p>
	 * 更新一个用户
	 * </p>
	 * 
	 * @param sysUser 要更新的用户
	 * @return ResponseEntity<ResultMsg>, json格式
	 * @throws URISyntaxException 如果URI语法不正确，则抛URI语法异常
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	@Parameter(name = "sysUser", description = "要更新的用户", required = false)
	@Operation(summary  = "更新，根据传递的 用户更新实体")
	@PostMapping("/sysUser/update")//在scheduletask里面是post
	public ResponseEntity<ResultMsg> update(
			@RequestBody SysUser sysUser)
			throws URISyntaxException {
		if (null == sysUser) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "更新用户失败，传递的用户为空"), HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("单条更新用户开始......", user.getLoginId(), user.getUsername(),
				getClientIp());
		// 若 用户无主键值，说明调用错误
		if (StringUtils.isBlank(sysUser.getUserId())) {
			log.info("单条更新用户失败，用户对象UserId无属性值", user.getLoginId(), user.getUsername(),
					getClientIp());
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "更新失败，用户对象UserId无属性值"), HttpStatus.OK);
		}
		sysUser.setSysOrganize(sysOrganizeService.getByNodeId(sysUser.getSysOrganize().getNodeId()));
		SysUser result = sysUserService.save(sysUser);
		log.info("单条更新用户成功", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "更新成功", result), HttpStatus.OK);
	}

	/**
	 * <p>
	 * 查询用户列表，若分页，则页码信息在Request的参数中，包括当前页，每页记录数
	 * </p>
	 * 
	 * @return ResponseEntity<QueryResult<SysUser>>，json格式
	 * @throws URISyntaxException 如果出错，则产生页码信息的 HTTP headers
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	
	@Operation(summary  = "查询，根据传递的条件查询用户列表，条件参数在Request中")
	@GetMapping("/sysUser/getAll")
	
	public ResponseEntity<ResultMsg> getAll()
			throws URISyntaxException, JsonParseException, JsonMappingException, IOException, ParseException {

		QueryFilter<SysUser> filter = new QueryFilter<SysUser>(SysUser.class);
		filter.addFilterFromRequest(request);
		QueryResult<SysUser> result = sysUserService.anyQuery(filter);
		if (null == result || null == result.getResultList() || result.getResultList().size() < 0) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "获取用户列表失败"), HttpStatus.OK);
		}
		
		/**
		 * 添加addsort
		 */
		filter.addSort("sysOrganize.organizeName", Sort.ASC);
		result = sysUserService.anyQuery(filter);
		

		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "获取列表成功", result.getResultList()), HttpStatus.OK);
	}
	
	@Operation(summary  = "查询，根据传递的条件查询用户列表，条件参数在Request中")
	@GetMapping("/sysUser/getAlls")
	
	public ResponseEntity<ResultMsg> getAlls()
			throws URISyntaxException, JsonParseException, JsonMappingException, IOException, ParseException {

		QueryFilter<SysUser> filter = new QueryFilter<SysUser>(SysUser.class);
		filter.addSort("sysOrganize.organizeName", Sort.ASC);
		QueryResult<SysUser> result = sysUserService.anyQuery(filter);
		if (null == result || null == result.getResultList() || result.getResultList().size() < 0) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "获取用户列表失败"), HttpStatus.OK);
		}

		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "获取列表成功", result.getResultList()), HttpStatus.OK);
	}
	/**
	 * <p>
	 * 根据用户唯一ID值获取用户
	 * </p>
	 * 
	 * @param id 用户唯一ID值
	 * @return ResponseEntity<SysUser>
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	@Parameter(name = "id", description = "对象唯一Id", required = false)
	@Operation(summary  = "获取单个用户，若根据用户唯一Id获取到了多个对象则发生异常")
	@GetMapping("/sysUser/get/{id}")


	public ResponseEntity<ResultMsg> get(
			 @PathVariable String id) {
		if (StringUtils.isBlank(id)) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "获取单个用户失败，未给定用户的唯一标识"), HttpStatus.OK);
		}
		SysUser sysUser = sysUserService.get(id);
		/*
		 * <p> ofNullable执行逻辑：如果对象为空，则执行orElse，否则执行.map... return
		 * Optional.ofNullable(sysRole).map(result -> new ResponseEntity<>(result,
		 * HttpStatus.OK)) .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
		 */

		if (null == sysUser) {

			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "获取单个用户失败，给定的用户可能被删除"), HttpStatus.OK);
		}

		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "获取成功", sysUser), HttpStatus.OK);
	}

	/**
	 * <p>
	 * 根据用户唯一ID值删除单个用户
	 * </p>
	 * 
	 * @param id 用户唯一ID值
	 * @return ResponseEntity,json格式
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	
	@Parameter(name = "id", description = "用户唯一Id", required = false)
	@Operation(summary  = "删除单个用户")
	@GetMapping("/sysUser/delete/{id}")
	public ResponseEntity<ResultMsg> delete(
			@PathVariable String id) {
		if (StringUtils.isBlank(id)) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "删除单个用户失败，未给定用户的唯一标识"), HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("删除单条用户开始......", user.getLoginId(), user.getUsername(),
				getClientIp());
		sysUserService.remove(id);
		log.info("删除单条用户成功", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "删除成功"), HttpStatus.OK);
	}

	/**
	 * <p>
	 * 根据用户唯一ID值集合，批量删除用户
	 * </p>
	 * 
	 * @param ids 用户唯一ID值集合
	 * @return ResponseEntity<ResultMsg>,返回结果中有删除的记录数，json格式
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	@Parameter(name = "ids", description = "逗号分隔的用户Id集合", required = false)
	@Operation(summary  = "删除用户集合")
	@PostMapping("/sysUser/deleteBatch")
	
	public ResponseEntity<ResultMsg> deleteBatch(
			@RequestParam String ids) {
		if (StringUtils.isBlank(ids)) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "批量删除用户失败，未给定用户的唯一标识集合"), HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("批量删除用户开始......", user.getLoginId(), user.getUsername(),
				getClientIp());
		long rows = sysUserService.deleteBatch(ids);
		log.info("批量删除用户成功", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "批量删除用户成功", rows), HttpStatus.OK);
	}

	/**
	 * <p>
	 * 根据用户唯一ID值集合，批量更新用户
	 * </p>
	 * 
	 * @param ids            用户唯一ID值集合
	 * @param properityName  用户要更新的属性名，不带类名
	 * @param properityValue 用户要更新的属性值
	 * @return ResponseEntity<ResultMessage>,返回结果中有更新的记录数，json格式
	 * @author Codegen-代码生成器
	 * @date 2020-06-01 16:49:18
	 */
	@Parameters({
		@Parameter(name = "properityName", description = "要更新的属性名不带类名，只能是类单个属性名且不能是集合类型", required = false),
		@Parameter(name = "properityValue", description = "属性值", required = false) ,
		@Parameter(name = "ids", description = "逗号分隔的用户Id集合", required = false)
	})
	@Operation(summary  = "更新用户集合")
	@PostMapping("/sysUser/updateBatch")
	public ResponseEntity<ResultMsg> updateBatch(
			 @RequestParam String properityName,
			@RequestParam String properityValue,
			@RequestParam String ids) {
		if (StringUtils.isBlank(ids) || StringUtils.isBlank(properityValue) || StringUtils.isBlank(properityName)) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "批量更新用户失败，未给定用户的唯一标识集合或属性名或属性值"), HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("批量更新用户开始......", user.getLoginId(), user.getUsername(),
				getClientIp());
		long rows = sysUserService.updateBatch(properityName, properityValue, ids);
		log.info("批量更新用户成功", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "批量更新用户成功", rows), HttpStatus.OK);
	}
	
	/**
	 * 
	 * <p> 授权  </p>  
	 * @param ids
	 * @param userId
	 * @return
	 * @return ResponseEntity<ResultMsg>
	 * @throws  
	 * @author shijunwei  
	 * @date 2020年6月1日 
	 * @time 下午5:27:38
	 */
	@Parameters({
		@Parameter(name = "ids", description = "id集合", required = false),
		@Parameter(name = "pkId", description = "用户Id", required = false) })
	@Operation(summary  = "授权")
	@GetMapping("/sysUser/impower")

	public ResponseEntity<ResultMsg> impower(@RequestParam("ids") String ids, @RequestParam("pkId") String userId) {
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		ResultMsg resultMessage = sysUserService.impower(ids, userId);
		log.info("给用户授权了资源", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<>(resultMessage, HttpStatus.OK);
	}

	
	/**
	 * 
	 * <p>
	 * 启用或者禁用
	 * </p>
	 * 
	 * @param 
	 * @return
	 * @return ResponseEntity<ResultMsg>
	 * @throws @author shijunwei
	 * @date 2020年6月1日
	 * @time 下午5:30:39
	 */
	
	@Parameter(name = "ids", description = "id集合", required = false)
	@Operation(summary  = "启用或者禁用")
	@GetMapping("/sysUser/enableOrDisable/{ids}")
	public ResponseEntity<ResultMsg> enableOrDisable(@PathVariable String ids) {
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		ResultMsg resultMessage = sysUserService.enableOrDisable(ids);
		log.info("给用户重置了状态", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<>(resultMessage, HttpStatus.OK);
	}
	
	/**
	 * 
	 * <p> 重置密码
	 * @param ids
	 * @return
	 * @return ResponseEntity<ResultMsg>
	 * @throws  
	 * @author shijunwei  
	 * @date 2020年6月1日 
	 * @time 下午5:31:34
	 */
	
	@Parameter(name = "ids", description = "id集合", required = false)
	@Operation(summary  = "根据id重置密码")
	@GetMapping("/sysUser/resetPassword/{ids}")
	public ResponseEntity<ResultMsg> resetPassword(@PathVariable String ids) {
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		ResultMsg resultMessage = sysUserService.resetPassword(ids);
		log.info("给用户重置了密码", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<>(resultMessage, HttpStatus.OK);
	}
	
	/**
	 * 
	 * <p> 检验密码 
	 * @param password
	 * @return
	 * @return String
	 * @throws  
	 * @author shijunwei  
	 * @date 2020年6月1日 
	 * @time 下午5:38:22
	 */
	
	@Parameter(name = "password", description = "密码", required = false)
	@Operation(summary  = "检验密码")
	@PostMapping(value = { "/sysUser/checkPassword" })
	public String checkPassword(@RequestParam String password) {
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		if (EncryptUtil.passwordEncoder("bcrypt").encode(password).equals(user.getPassword()))
			return "{success:true}";
		else
			return "{seccess:false}";
	}
	
	/**
	 * 
	 * <p> 修改密码 
	 * @param password
	 * @param loginId
	 * @return
	 * @return ResponseEntity<ResultMessage>
	 * @throws  
	 * @author shijunwei  
	 * @date 2020年6月1日 
	 * @time 下午5:38:58
	 */
	
	@Parameter(name = "newPassword", description = "新密码", required = false)
	@Operation(summary  = "修改密码")
	@PostMapping("/sysUser/changePassword")
	public ResponseEntity<ResultMessage> changePassword(@RequestParam("newPassword") String password,
			@RequestParam("loginId") String loginId) {
		SysUser sysUser = sysUserService.findByLoginId(loginId);
		sysUser.setPassword(StringUtils.encryptSha256(password));
		sysUserService.save(sysUser);
		return new ResponseEntity(new ResultMessage(true), HttpStatus.OK);
	}

	/**
	 * \ 修改个人信息时得到用户信息
	 * <p>
	 * Description:
	 * </p>
	 * <p>
	 * Company:上海信拓
	 * </p>
	 * 
	 * @param @return
	 * @author ly
	 * @date 2017年6月27日下午15:35:28
	 */
	
	@Operation(summary  = "修改个人信息时得到用户信息")
	@PostMapping("/sysUser/loadUser")
	public ResponseEntity<SysUser> loadUser() {
		SysUser sysUser = (SysUser)SecurityUtils.getLoginedUser();
		String userId = sysUser.getUserId();
		SysUser user = sysUserService.get(userId);
		return Optional.ofNullable(user).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
				.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));

	}


	/**
	 * @Description 修改个人信息
	 * @Param file
	 * @Param email
	 * @Param loginId
	 * @Param descript
	 * @return org.springframework.http.ResponseEntity<com.xtsoft.core.utils.ResultMessage>
	 * @Author defencez
	 * @Date 2024-04-21 13:47
	*/
	@Parameters({
		@Parameter(name = "filePath", description = "文件路径", required = false),
		@Parameter(name = "email", description = "邮箱", required = false),
		@Parameter(name = "loginId", description = "登录Id", required = false),
		@Parameter(name = "descript", description = "描述", required = false)
		
	})
	@Operation(summary  = "修改个人信息")
	@PostMapping("/sysUser/saveUser")
	public ResponseEntity<ResultMessage> saveUser(
			@RequestParam(value = "filePath", required = false) MultipartFile file,
			@RequestParam("email") String email,
			@RequestParam("loginId") String loginId,
			@RequestParam(value = "descript", required = false) String descript) throws IOException {
		String absolutePath = "";
		if (!file.isEmpty()) {
			byte[] bytes = file.getBytes();
			String uuid = UUIDGenerator.getUUID();
			String fileName = file.getOriginalFilename().replace("\"", "“");
			String path = request.getSession().getServletContext().getRealPath("/") + "/upload/" + uuid;// 绝对路径
			absolutePath = "/upload/" + uuid + "/" + fileName;// 相对路径
			Path dirpath = Paths.get(path);// 文件夹路径
			Path filepath = Paths.get(dirpath + "/" + fileName);// 文件路径
			Files.createDirectories(dirpath);// 创建文件夹
			Files.write(filepath, bytes);// 创建文件
		}
		SysUser sysUser = sysUserService.findByLoginId(loginId);
		if (!StringUtils.isEmpty(absolutePath)) {
			sysUser.setFilePath(absolutePath);
		}
		sysUser.setDescript(descript);
		sysUser.setEmail(email);
//    	   sysUser.setPassword(StringUtils.encryptSha256(password));
		sysUserService.save(sysUser);
		return new ResponseEntity(new ResultMessage(true, absolutePath), HttpStatus.OK);
	}

	/**
	 * @Description 修改个人信息
	 * @Param file
	 * @Param email
	 * @Param loginId
	 * @Param descript
	 * @return org.springframework.http.ResponseEntity<com.xtsoft.core.utils.ResultMessage>
	 * @Author defencez
	 * @Date 2024-04-21 13:47
	 */
	@Parameters({
			@Parameter(name = "filePath", description = "文件路径", required = false),
			@Parameter(name = "email", description = "邮箱", required = false),
			@Parameter(name = "loginId", description = "登录Id", required = false),
			@Parameter(name = "descript", description = "描述", required = false)

	})
	/**
	 * @Description 登录测试
	 * @Param user
	 * @return org.springframework.http.ResponseEntity<com.xtsoft.core.utils.ResultMessage>
	 * @Author defencez
	 * @Date 2024-04-23 14:44
	*/
	@Operation(summary  = "登录")
	@Parameter(name = "user" , description = "用户")
	@PostMapping("/sysUser/login")
	public ResponseEntity<ResultMessage> login(@RequestBody Map<String, String> param){
		try {
			String username = param.get("username");
			String password = param.get("password");
			String reqType = param.get("type");

			// 传递用户密码给到SpringSecurity执行校验，如果校验失败，会进入BadCredentialsException
			Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
			// 验证通过，设置授权信息至SecurityContextHolder
			SecurityContextHolder.getContext().setAuthentication(authentication);

			// 如果验证通过了，从返回的authentication里获得完整的UserDetails信息
			SysUser userDetails = (SysUser) authentication.getPrincipal();

			// 将用户的ID、名称等信息保存在jwt的token中
			String token = jwtTokenProvider.createToken(userDetails);

			// 设置cookie，本项目中非必需，因以要求必须传head的Authorization: Bearer 参数
			//ResponseCookie jwtCookie = jwtTokenProvider.generateJwtCookie(token);
			Map<String, Object> model = new HashMap<>();
			model.put("username", username);
			model.put("token", token);
			return ok(new ResultMessage(true, "成功", model));
		} catch (Exception e) {
			return ok(new ResultMessage(false, e.getMessage()));
		}
	}



}
